/**
 * Copyright 2007-2008. Chongqing First Information & Network Co., Ltd. All
 * rights reserved. <a>http://www.cqfirst.com.cn</a>
 */
package com.cqcis.uip.base.framework.handlers.common;

import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.mina.common.IdleStatus;
import org.apache.mina.common.IoHandler;
import org.apache.mina.common.IoSession;

import com.cqcis.uip.base.framework.FrameworkConstants;
import com.cqcis.uip.base.framework.common.Task;
import com.cqcis.uip.base.framework.core.RegisteredService;
import com.cqcis.uip.base.framework.core.TaskResultProcessor;
import com.cqcis.uip.base.framework.service.InterfaceLogService;
import com.cqcis.uip.base.framework.service.impl.DefaultInterfaceLogService;
import com.cqcis.uip.base.framework.utils.ConcurrentTaskQueue;


/**
 * @author huangmy
 * @date 2007-12-4
 */
public abstract class AbstractSocketHandler extends AbstractHandler 
                implements IoHandler, TaskResultProcessor {
	private static Log log = LogFactory.getLog(AbstractSocketHandler.class);	
	protected static String SESSION_SERVICE_EXCEPTION = "SESSION_EXCEPTION_" + AbstractSocketHandler.class;
	protected long timeout;        /*超时时间*/
	private InterfaceLogService interfaceLogService;
	private RegisteredService adaptorRS;// 关联的注册服务
    private boolean streamRecord; // 字节流记录
    private Runnable askForSession;// 申请session
	
	public void registerStreamRecord(boolean streamRecord) {
		this.streamRecord = streamRecord;		
	}
	
	protected boolean isStreamRecord() {
		return this.streamRecord;
	}
	
	public void messageReceived(IoSession session, Object message)
			throws Exception {		
		session.setIdleTime(IdleStatus.READER_IDLE, 0);
		
		try {
		    doMessageReceived(session,  message);
		} catch (Exception t) {
			session.setAttribute(SESSION_SERVICE_EXCEPTION, Boolean.TRUE);
			throw t;
		}
	}

	public void exceptionCaught(IoSession session, Throwable cause)
			throws Exception {		
		log.error("exceptionCaught: session = " + session, cause);
		try {
		    doExceptionCaught(session, cause);
		} catch(Throwable t) {
			log.error("doExceptionCaught Throwable: ", t);
		} finally {
			if (session != null) { // 业务层异常，不关闭链接
				if (session.removeAttribute(SESSION_SERVICE_EXCEPTION) == null) {
					session.close();
				} else {
					idleSessionTo(session);
				}				
			}
		}
	}
	
	/**
	 * 处理session
	 * 
	 * @param session
	 */
	protected abstract void idleSessionTo(IoSession session);
	
	/**
	 * 二进制日志路径
	 * 
	 * @param file
	 * @return
	 */
	protected String getRecordPathFrom(String file) {
		if (file == null) {
			return null;
		}
		int splitBegin = file.indexOf(FrameworkConstants.STREAM_LOG_PATH_STOKEN);
		if (splitBegin >= 0) {
			splitBegin = splitBegin + FrameworkConstants.STREAM_LOG_PATH_STOKEN.length() + 1;
		} else {
			splitBegin = 0;
		}
		
		return file.substring(splitBegin);
	}
    
	public void sessionOpened(IoSession session) throws Exception {	
		doSessionOpened(session);
	}
	
	public void sessionCreated(IoSession session) throws Exception {
		if ((adaptorRS != null 
				&& adaptorRS.getAttributes().getAttribute(FrameworkConstants.STREAM_LOG_NOT_WRITED) != null)
				|| (!isStreamRecord())) {
			// 不备份日志文件
			session.setAttribute(FrameworkConstants.STREAM_LOG_NOT_WRITED, "true");
		}
		
		doSessionCreated(session);
	};
	
	public void messageSent(IoSession session, Object message) throws Exception {		
		doMessageSent(session, message);
	}
		
	/**
	 * 获取所有的连接
	 * 
	 * @param session
	 * @return
	 */
	protected Set<IoSession> getAllSessions(IoSession session) {
		return session.getService().getManagedSessions(session.getServiceAddress());
	}
	
	public void sessionClosed(IoSession session) throws Exception {			
		doSessionClosed(session);
		
		Set<IoSession> sessions = getAllSessions(session);
		if (sessions != null && sessions.size() == 0) {					
			ConcurrentTaskQueue<Task> taskQueue = getTaskQueue();
			if (taskQueue != null && taskQueue.size() > 0) {
				// 请求新建session
				if (this.askForSession != null) {
					this.askForSession.run();
				}				
			}
		}		
	}
	
	public void sessionIdle(IoSession session, IdleStatus status)
			throws Exception {		
		doSessionIdle(session, status);		
	}
    
	protected void doSessionOpened(IoSession session) throws Exception {		
	}
	
	/**
	 * session建立
	 * @param session
	 * @throws Exception
	 */
	protected abstract void doSessionCreated(IoSession session) throws Exception;
	
	/**
	 * 收到消息
	 * @param session
	 * @param message
	 * @throws Exception
	 */
	protected abstract void doMessageReceived(IoSession session, Object message) throws Exception;
	
	/**
	 * 消息发送后
	 * @param session
	 * @param message
	 * @throws Exception
	 */
	protected abstract void doMessageSent(IoSession session, Object message) throws Exception;
	
	/**
	 * 异常发生
	 * @param session
	 * @param cause
	 * @throws Exception
	 */
	protected abstract void doExceptionCaught(IoSession session, Throwable cause) throws Exception;	
	
	/**
	 * session关闭
	 * @param session
	 * @throws Exception
	 */
	protected abstract void doSessionClosed(IoSession session) throws Exception;	
	
	/**
	 * 空闲
	 * @param session
	 * @param status
	 * @throws Exception
	 */
	protected abstract void doSessionIdle(IoSession session, IdleStatus status) throws Exception;
	
	/**
	 * 获取传入信息的任务ID
	 * @param message 传给业务层的消息实例
	 * @return
	 */
	protected abstract Task getBeforeTask(Object message);
	
	/**
	 * 获取传入信息的任务ID
	 * @param writeMessage 需要发送给对方的消息实例
	 * @return
	 */
	protected abstract Task getAfterTask(Object writeMessage);
    
	public void registerTimeout(long timeout) {
		this.timeout = timeout;
	}
	
	protected long getTimeout() {
		return this.timeout;
	}
	
	public void registerInterfaceLogService(InterfaceLogService interfaceLogService) {
		if (interfaceLogService != null) {
			this.interfaceLogService = new DefaultInterfaceLogService(interfaceLogService);
		}		
	}
	
	public void registerAdaptorRS(RegisteredService adaptorRS) {
		this.adaptorRS = adaptorRS;
	}
	
	protected InterfaceLogService getInterfaceLogService() {
		if (this.interfaceLogService == null) {
			this.interfaceLogService = new DefaultInterfaceLogService();
		}
		
		return this.interfaceLogService;
	}
	
	/**
	 * 获取session
	 * 
	 * @return
	 */
	public Runnable getAskForSession() {
		return this.askForSession;
	}
    
	public void registerAskForSession(Runnable askForSession) {
		this.askForSession = askForSession;
	}
}
